package com.chenl.provider.DEMOS.Spring.Spring事务相关;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
public class TransactionUtils {
    private static ThreadFactory springThreadFactory = new CustomizableThreadFactory("My-Transaction-Thread-");
    private static ThreadPoolExecutor executorPool = new ThreadPoolExecutor(10,
            200,
            1,
            TimeUnit.MINUTES,
            new LinkedBlockingQueue<>(100000),
            springThreadFactory,
            new ThreadPoolExecutor.AbortPolicy());

    /**
     * 传入任务，在事务提交或回滚时进行相应的操作,当前方法必须开启事务方可生效
     *
     * @param commitRunnable   成功提交时执行
     * @param rollbackRunnable 回滚时执行
     */
    public static void doAfterTransaction(Runnable commitRunnable, Runnable rollbackRunnable) {
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(new DoTransactionCompletion(commitRunnable, rollbackRunnable));
        }
    }

    static class DoTransactionCompletion implements TransactionSynchronization {
        private Runnable commitRunnable;
        private Runnable rollbackRunnable;

        public DoTransactionCompletion(Runnable commitRunnable, Runnable rollbackRunnable) {
            this.commitRunnable = commitRunnable;
            this.rollbackRunnable = rollbackRunnable;
        }

        /**
         * 在事务完成后根据状态进行相应的操作
         *
         * @param status
         */
        @Override
        public void afterCompletion(int status) {
            if (status == TransactionSynchronization.STATUS_COMMITTED&&this.commitRunnable!=null) {
                executorPool.execute(this.commitRunnable);
            }else if (status == TransactionSynchronization.STATUS_ROLLED_BACK&&this.rollbackRunnable!=null){
                executorPool.execute(this.rollbackRunnable);
            }
        }
    }
}
